-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8369609: Continuations preempt_epilog is missing a call to invalidate_jvmti_stack #27878
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
👋 Welcome back sspitsyn! A progress list of the required criteria for merging this PR into |
|
@sspitsyn This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 30 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
Webrevs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for fixing this Serguei.
|
|
||
| log_develop_debug(continuations)("=== End of freeze cont ### #" INTPTR_FORMAT, cont.hash()); | ||
|
|
||
| JVMTI_ONLY(invalidate_jvmti_stack(JavaThread::current())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not directly in preempt_epilog? Is it to cover the freeze fast case too? If that’s the case we should remove the call to invalidate_jvmti_stack from jvmti_yield_cleanup to avoid calling it twice for the freeze slow case. Also I wonder if this call to invalidate_jvmti_stack should just be moved to JvmtiVTMSTransitionDisabler::VTMS_unmount_end instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the comment! Yes, I had in mind but forgot to remove the call to invalidate_jvmti_stack() from jvmti_yield_cleanup(). I've pushed the update now.
Also I wonder if this call to invalidate_jvmti_stack should just be moved to JvmtiVTMSTransitionDisabler::VTMS_unmount_end instead.
Unfortunately, this is not going to work for plain/pure continuations as mount/unmount code path does not work for them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. What do you think about adding invalidate_jvmti_stack in jvmti_yield_cleanup if !cont.entry()->is_virtual_thread() is true to address that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea! It'd be nice to move the invalidate_jvmti_stack() calls out of the continuation code. I'll test it and let you know the results.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strangely, the test serviceability/jvmti/vthread/ContStackDepthTest is failing with the assert(_cur_stack_depth == num_frames). Obviously, some of the code paths is missed to call invalidate_jvmti_stack().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, we need to call invalidate_jvmti_stack at the end in jvmti_yield_cleanup! The problem is that in JvmtiExport::continuation_yield_cleanup we are setting again the stack depth when calling state->cur_stack_depth(). We count the enterSpecial frame at the top but we don’t decrement the depth when removing it (done in assembly code).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, thanks! Did you verify it with run of test serviceability/jvmti/vthread/ContStackDepthTest? I see it is still failing with the call to invalidate_jvmti_stack() at the end of jvmti_yield_cleanup().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test does not fail with the following patch:
diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp
index 0750f611876..a12e99903af 100644
--- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp
+++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp
@@ -1626,12 +1626,17 @@ static void invalidate_jvmti_stack(JavaThread* thread) {
}
static void jvmti_yield_cleanup(JavaThread* thread, ContinuationWrapper& cont) {
- if (!cont.entry()->is_virtual_thread() && JvmtiExport::has_frame_pops(thread)) {
+ if (cont.entry()->is_virtual_thread()) {
+ return;
+ }
+ invalidate_jvmti_stack(thread);
+ if (JvmtiExport::has_frame_pops(thread)) {
int num_frames = num_java_frames(cont);
ContinuationWrapper::SafepointOp so(Thread::current(), cont);
- JvmtiExport::continuation_yield_cleanup(JavaThread::current(), num_frames);
+ JvmtiExport::continuation_yield_cleanup(thread, num_frames);
}
+ invalidate_jvmti_stack(thread);
}
static void jvmti_mount_end(JavaThread* current, ContinuationWrapper& cont, frame top) {
@@ -1685,7 +1690,6 @@ static inline freeze_result freeze_epilog(ContinuationWrapper& cont) {
log_develop_debug(continuations)("=== End of freeze cont ### #" INTPTR_FORMAT, cont.hash());
- JVMTI_ONLY(invalidate_jvmti_stack(JavaThread::current()));
return freeze_ok;
}
@@ -2311,7 +2315,7 @@ NOINLINE intptr_t* Thaw<ConfigT>::thaw_slow(stackChunkOop chunk, Continuation::t
assert(_cont.chunk_invariant(), "");
- JVMTI_ONLY(invalidate_jvmti_stack(_thread));
+ JVMTI_ONLY(if (!_cont.entry()->is_virtual_thread()) invalidate_jvmti_stack(_thread));
_thread->set_cont_fastpath(_fastpath);
The call to invalidate_jvmti_stack() is still needed in the thaw_slow().
I can go ahead with this update if you are okay with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the patch I tested out with serviceability/jvmti/vthread/ContStackDepthTest (on top of mainline):
diff --git a/src/hotspot/share/prims/jvmtiThreadState.cpp b/src/hotspot/share/prims/jvmtiThreadState.cpp
index 00a48dec111..181d77f4d10 100644
--- a/src/hotspot/share/prims/jvmtiThreadState.cpp
+++ b/src/hotspot/share/prims/jvmtiThreadState.cpp
@@ -678,6 +678,10 @@ void
JvmtiVTMSTransitionDisabler::VTMS_unmount_end(jobject vthread) {
JavaThread* thread = JavaThread::current();
assert(thread->is_in_VTMS_transition(), "sanity check");
+ JvmtiThreadState *state = thread->jvmti_thread_state();
+ if (state != nullptr) {
+ state->invalidate_cur_stack_depth();
+ }
finish_VTMS_transition(vthread, /* is_mount */ false);
}
diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp
index 3e509e71551..a493fca076e 100644
--- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp
+++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp
@@ -1626,13 +1626,15 @@ static void invalidate_jvmti_stack(JavaThread* thread) {
}
static void jvmti_yield_cleanup(JavaThread* thread, ContinuationWrapper& cont) {
- if (!cont.entry()->is_virtual_thread() && JvmtiExport::has_frame_pops(thread)) {
- int num_frames = num_java_frames(cont);
+ if (!cont.entry()->is_virtual_thread()) {
+ if (JvmtiExport::has_frame_pops(thread)) {
+ int num_frames = num_java_frames(cont);
- ContinuationWrapper::SafepointOp so(Thread::current(), cont);
- JvmtiExport::continuation_yield_cleanup(JavaThread::current(), num_frames);
+ ContinuationWrapper::SafepointOp so(Thread::current(), cont);
+ JvmtiExport::continuation_yield_cleanup(JavaThread::current(), num_frames);
+ }
+ invalidate_jvmti_stack(thread);
}
- invalidate_jvmti_stack(thread);
}
static void jvmti_mount_end(JavaThread* current, ContinuationWrapper& cont, frame top) {
Originally I had invalidate_jvmti_stack() before calling JvmtiExport::continuation_yield_cleanup so I could reproduce the issue.
I think you are right that for virtual threads we shouldn't need to invalidate the stack, so your patch is an improvement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, thanks! I've pushed my latest changes which are aligned with your patch above and invalidate the stack for plain/pure continuations only. So, the VTMS_unmount_end() still does not include it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, thanks Serguei!
|
Patricio, thank you a lot for review a suggestions! |
This is a simple fix to add missing call to
invalidate_jvmti_stack()to thefreeze_epilog(ContinuationWrapper& cont).Testing:
Progress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/27878/head:pull/27878$ git checkout pull/27878Update a local copy of the PR:
$ git checkout pull/27878$ git pull https://git.openjdk.org/jdk.git pull/27878/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 27878View PR using the GUI difftool:
$ git pr show -t 27878Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/27878.diff
Using Webrev
Link to Webrev Comment